#!/usr/bin/perl
#################################################################################################
#    log2timeline
#################################################################################################
# This script is a part of the the program log2timeline that is designed to parse a log file,
# any supported log file, and output it in a bodyfile that can be read by supporting software for
# timeline creation.
#
# The default behaviour of the tool is to outpt in a CSV format.
#
# This script serves as the front-end for the program and it's purpose is to
# read all parameters, find and load the appropriate format file, a perl script that is designed
# to read a particular file format, and print the information found in the file in a body format.
# The script also holds some methods that are used in more than one format file (instead of repeating
# the code)
#
# The specification for the TLN body file format can be found here:
#  http://windowsir.blogspot.com/2010/02/timeline-analysisdo-we-need-standard.html
#
# The specification of the body file can be found here (the mactime body file):
#  http://wiki.sleuthkit.org/index.php?title=Body_file
#
# As said before this is the main script, it parses all arguments as well as to call other
# scripts needed to parse the actual log files. The parsing of log files is done in a so
# called format file, where each format file provides a method to parse different log format.
#
# This script then gets the output from the format file, and uses it to print out a bodyfile
# that can be used in TSK (default behaviour)
#
# Author: Kristinn Gudjonsson
# Date : 20/05/10
#
# Copyright 2009-2011 Kristinn Gudjonsson (kristinn ( a t ) log2timeline (d o t) net)
#
#  This file is part of log2timeline.
#
#    log2timeline is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    log2timeline is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with log2timeline.  If not, see <http://www.gnu.org/licenses/>.
#
# Uses method Win2Unix written by A. Schuster and C. Barta from ptfinder.pl
# Copyright (c) 2009 by Andreas Schuster and Csaba Barta.

use strict;

<<<<<<< HEAD
use Time::localtime;	# for time conversion
use Getopt::Long; 	# read parameters
use Pod::Usage;		# for man and help messages
use LWP::UserAgent;	# to get the version number from the web
use DateTime::TimeZone;	# for time zones,
use Log2Timeline;	# the main engine of log2timeline
use Digest::MD5;	# for MD5 sum calculation
use Encode;

# define variables
my @dir_content;
my $plug;

my $line;
my @lines;
my $t_line;
my $p_line;
my $verify;

my $log_file;
my $temp;
my @args; # an array that contains the arguments

# for parameters
my $show_version = 0;
my $print_help = 0;
my $time_offset = 0;
my $textfield = '';
my $format= '';
my $hostname = 'unknown';	# a variable defining the hostname
my $output_file = 'csv';
my $out_file = 'STDOUT';
my $detail = 0;	# a variable defining if we should skip the quick test in the verification phase
my $log_file = '';
my $file_exists = 0;
my $format_file;
my $temp_file = '';	# the default value for the temporary file location (it is automatically detected if this option is used)
my $output;
my $check = 0;
my $timezone = undef;
my $out_timezone = undef;
my $time_object;
my $debug = 0;
my $digest = 0;	# defines whether or not a MD5 sum is to be calculated
my $recursive = 0;	# recursive search or not?
my $preproc = 0;	# do we want to run pre-processing modules
my $exclude = '';	# an exclusion list (list of files we would like to exclude from parsing)
my @input_arguments;
my $mft_detail = 0; 	# determine if mft module prints $FN timestamps

# record the start time...
my $start_time = time();

# for message digest
my ($sum,%last_sum);

# the l2t object
my $l2t;

# configure the getoptions
Getopt::Long::Configure("no_ignore_case");

# read options
GetOptions( 
	"skew=s"=>\$time_offset,
	"m=s"=>\$textfield,
	"verbose+"=>\$debug,
	"upgrade!" => \$check,
	"calculate!" => \$digest,
	"format|f=s"=>\$format_file,
	"Version!"=>\$show_version,
	"x!" => \$detail,
	"name=s" => \$hostname,
	"output=s"=>\$output_file,
	"write=s"=>\$out_file,
	"log=s"=>\$log_file,
	"recursive!"=>\$recursive,
	"detail!"=>\$mft_detail,
	"preprocess!"=>\$preproc,
	"zone=s"=>\$timezone,
	"Zone=s"=>\$out_timezone,
	"exclude=s"=>\$exclude,
	"temp|t=s"=> \$temp_file,
	"args=s" => \@input_arguments,
        "help|?!"=>\$print_help
) or pod2usage( 2 );

# create the log2timeline object
$l2t = Log2Timeline->new(  ) or pod2usage( { 	
	-message	=> "Unable to create the Log2Timeline object, unable to continue",
	-verbose	=> 1,
	-exitval	=> 4 } );

# check if the object is valid (the constructor was able to complete)
pod2usage( { 	
	-message	=> "The Log2Timeline object is not valid, cannot continue. The dreaded case of an 'Unknown error'.",
	-verbose	=> 1,
	-exitval	=> 5 } ) unless $l2t->is_valid;

# check to see if we want all log messages written to a specific log file (or just to STDERR)
if( $log_file ne '' )
{
	open( STDERR, '>' . $log_file );
}

# check options
if( $show_version )
{
	my @t;
	@t = split( /\//, $0 ) unless $^O =~ m/MSWin/;
	@t = split( /\\/, $0 ) if $^O =~ m/MSWin/;
	print $t[$#t] . " version " . $l2t->version . "\n";
	exit 0;
}

if( $check )
{
	# check the latest version
	print STDERR $l2t->check_upgrade . "\n";

	exit 0;
}

# check if we want to print the help message
if ( $print_help )
{
	# check if the option -f is also used, then we print the format file help as well
	if( $format_file ne '' && $format_file ne 'list' )
	{
		eval
		{
			# print the help message
			print STDERR $l2t->get_help_in( $format_file ) . "\n";
		};
		# check if we were unable to load the format file
		if( $@ )
		{
			pod2usage( { 	
				-message	=> "Unable to load input module [$format], so no help is printed (try $0 -f list to see available input modules)\nThe error message is: $@",
				-verbose	=> 1,
				-exitval	=> 12 } );
		}
	}
	else
	{
		# then we print the help message
		print STDERR "\n\n";
		print STDERR "-------------------------------------------------\n";
		pod2usage(1);
	}
	exit 0;

}

# check the temporary file
unless ( $temp_file eq '' )
{
	# now we need to check the temporary folder, to see if it exists
	pod2usage( { 	
		-message	=> "The temporary folder ($temp_file) does not exist, it has to exist for the tool to able to use it.\n",
		-verbose	=> 1,
		-exitval	=> 8 } ) unless -d $temp_file;

        # set the separator
	my $p;
	
	$p = $temp_file . '\\bla.txt' if $^O =~ m/MSWin/i;
	$p = $temp_file . '/bla.txt' unless $^O =~ m/MSWin/i;


	# now the folder exists, let's check if we can write a file to it...
	pod2usage( { 	
		-message	=> "The temporary folder ($temp_file) does not exist, it has to exist for the tool to able to use it.\n",
		-verbose	=> 1,
		-exitval	=> 8 } ) unless open(TF, '>' . $p );

	# remove this stuff
	close(TF);
	unlink( $p ) if -f $p;
	
}

# find format files, check if format = list (then we are supposed to print available formats)
if( $format_file eq "list" )
{
	eval
	{
		print $l2t->get_inputs;
	};
	if( $@ )
	{	
		pod2usage( { 	
			-message 	=> "Error, unable to parse input module.\nError message: $@",
			-verbose	=> 1,
			-exitval	=> 12  });
	}

	# since we do no parsing we exit from the program
	exit 0;
}

# check if we want to list all output plugins
if( $output_file eq "list" )
{
	eval
	{
		print Log2t::Common::list_output();
	};
	if( $@ )
	{	
		pod2usage( { 	
			-message 	=> "Error, unable to parse output module.\nError message: $@",
			-verbose	=> 1,
			-exitval	=> 13  });
	}
	exit 0;
}

# check if we are about to list timezone settings
if( $timezone eq "list" or $out_timezone eq "list" )
{
	print $l2t->get_timezone_list;
	exit 0;
}

# no we know that we are not printing a help message and not listing up available format files or output plugins
# so we are about to parse a log file, and then we need to know the format of the file 
# (there is no mechanism to detect the format of the log file, yet it might come in a future version)

# if no input module is defined, then we will use the "all", or guessing which module to use
$format_file = 'all' if $format_file eq '';
$format_file = 'all' if $format_file eq 'guess';

# test parameters, just to see if we have at least one parameter left on the command line (indicates that 
# a log file has been provided)
if( $#ARGV <  0  )
{
	pod2usage( { 	-message	=> "Wrong usage: no log file passed on", 
			-verbose	=> 1,
			-exitval	=> 1 } );
}

# check if timezone has been set or not
print STDERR "-----------------------------------------------------------------
			[WARNING] 
No timezone has been chosen so the local timezone of this
machine is chosen as the timezone of the suspect drive.

If this is incorrect, then cancel the tool and re-run it
using the -z TIMEZONE parameter to define the suspect drive
timezone settings (and possible time skew with the -s parameter)

(5 second delay has been added to allow you to read this message)
-----------------------------------------------------------------\n" unless defined $timezone;
sleep( 5 ) unless defined $timezone;
$timezone = 'local' unless defined $timezone;

# set the output timezone
$out_timezone = $timezone unless defined $out_timezone;


# check the timezone settings
eval 
{
	print STDERR "[LOG2TIMELINE] Testing time zone $timezone\n" if $debug;
	$time_object = DateTime::TimeZone->new( 'name' => "$timezone" );
};
if( $@ )
{
	pod2usage( { 	
		-message	=> "Timezone [$timezone] is not a valid timezone",
		-verbose	=> 1,
		-exitval	=> 45 } );
}

# assign the file name of the log file
$log_file = shift(@ARGV);

# check to see if this file/dir exists
if( -e $log_file || -d $log_file )
{
	# file exists
	print STDERR "Start processing file/dir [$log_file] ...\n";
}
else
{
	# the file/dir does not exist, exit the code
	pod2usage( { 	-message	=> "Wrong usage: log file [$log_file] does not exist (or unable to find it)", 
			-verbose	=> 1,
			-exitval	=> 1 } );
}

# print a log message
print STDERR "Starting to parse using input modules(s): [$format_file] \n";

# prepare the output file
if( $out_file eq 'STDOUT' )
{
	open( MYFILE, ">-" );
}
else
{
	# check if it exists
	$file_exists = 1 if -f $out_file;

	# we are redirecting to a file
	open( MYFILE, '>>' . $out_file );
}

# start by fixing the settings
eval
{
	$l2t->set(
		'file'          => $log_file,
		'recursive'     => $recursive,
		'input'         => $format_file,
		'output'        => $output_file,
		'time_zone'     => $timezone,
		'out_time_zone' => $out_timezone,
		'log_file'	=> $out_file,
		'offset'        => $time_offset,
                'exclusions'    => $exclude,
		'text'          => $textfield,
		'append'	=> $file_exists,
		'debug'         => $debug,
		'temp'		=> $temp_file,
		'digest'        => $digest,
		'quick'         => $detail,
                'raw'           => 0,
		'detailed_time'	=> $mft_detail,
		'hostname'      => $hostname,
		'preprocess'    => $preproc,
	);
};
if($@)
{
	pod2usage( { 	
		-message	=> "Unable to configure the log2timeline engine.  Error message: $@\n",
		-verbose	=> 1,
		-exitval	=> 11 } );
}


# check if the output file exists, and if it does, we need to 
# do some parsing to remove extra footer before appending to it
if ( $file_exists )
{
	# first verify that the footer actually contains data
	my $footer = $l2t->get_out_footer;

	if( ( $out_file ne 'STDOUT' ) && ( $footer ) )
	{    
		# we need to re-open the file read-only
		close( MYFILE );
		open( MYFILE, '<' . $out_file );
	
		# we have a footer and need to remove it
		
		# read the content of the file
		my @content = <MYFILE>;
		close(MYFILE);
	
		# remove the footer
		@content = grep{ !/$footer/ } @content;
	      
		# open the file up again and print the previous content - header
		open( MYFILE, '>' . $out_file );
		print MYFILE @content;
	}    
}   

eval
{
	$l2t->start;
};	
# check if there were errors loading the format file
if( $@ )
{
	pod2usage( { 	
		-message	=> "Unable to run the tool.  Error message given: $@\n",
		-verbose	=> 1,
		-exitval	=> 12 } );
}

# close the file
close( MYFILE );

# check if this was recursive... then we print out end time
printf STDERR "Run time of the tool: %s seconds\n", time() - $start_time if $recursive;

##############################################################################################################
#		COMMON SUBROUTINES
##############################################################################################################
# here follow routines that can be called by each of the format files, that is routines that are shared
# among all of the format files

# a simple routine to print a line
sub print_line($)
{
	my $line = shift;

	# print to the file in question
	#print MYFILE encode('utf8', $line ); 
	print MYFILE $line;
=======
print "This is a legacy script that will be removed, new name is: 'log2timeline_legacy'\n";
print "Removing: $0\n";
my $res = unlink $0;
unless ( $res ) {
  print "Unable to remove the file, perhaps run this script as an administrator (sudo?)\n";
>>>>>>> l2t/master
}
